<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>演示vue2、vue3数据绑定的原理</title>
</head>
<body>
  <h2>Vue2的做法  Object.defineProperties()</h2>
  <p id="v2p">1</p>
  <button id="v2btn">点我数字++</button>
  <!-- 右键 open width live server -->
  <script>
    // 模拟vue2中的data
    var data = { num:1 }
    // 模拟vue2中的方法，修改data，自动更新UI
    v2btn.onclick = function(){
      data.num++
    }

    // vue2的方式，监听data对象，一旦data对象中的属性发生变化，更新UI
    Object.defineProperties(data, {
      _num: { value:1, writable:true },
      num: {   // 监听data.num属性
        get(){  // 当用户访问data.num时，就会执行该get方法
          return this._num
        },
        set(value){  // 当用户修改 data.num=xx时，就会执行该set方法
          this._num = value
          // 修改变量值的通知，还需要更新p标签的内容
          let v2p = document.getElementById('v2p')
          v2p.innerHTML = value
        }
      }
    })    
  </script>

  <!-- vue3的做法 -->
  <h2>Vue3的做法  通过new Proxy()的方式创建代理对象</h2>
  <p id="v3p">10</p>
  <button id="v3btn">点我数字递增</button>
  <script>
  var v3data = { count:10 }
  // 为了修改v3data属性时，页面可以实时更新
  // 可以为v3data对象创建一个代理对象 new Proxy()
  let v3dataProxy = new Proxy(v3data, {
    // 当用户修改v3data代理对象的属性时，就会被该代理对象拦截 
    // 自动调用当前set方法，此处可以在修改属性值的同时，还可以更新UI
    set(obj, key, value){
      obj[key] = value  // 先修改目标对象的属性   本职工作
      v3p.innerHTML = value  // 顺带更新DOM
    },
    // 当用户访问v3data代理对象属性时，就会执行该get方法
    get(obj, key){
      return obj[key]
    }
  })

  v3btn.onclick = function(){
    v3dataProxy.count++
  }
  </script>

</body>
</html>





